from top_right_small_notification.base import *
from top_right_small_notification.widgets.statuswidget import Ui_StatusWidget

from PyQt5.QtGui import QPixmap


class StatusWidget(QWidget):
    """
    +-----------------------+
    | icon      title       |
    +-----------------------+
    |  message              |
    +-----------------------+
    """
    # enum 进入与退出方向
    class EnterLeaveDuretion(int):
        TopIn       = 1
        LeftIn      = 2
        RightIn     = 3
        BottomIn    = 4
        TopOut      = 5
        LeftOut     = 6
        RightOut    = 7
        BottomOut   = 8

    # 像 C++ 一样先定义一些内容，例如
    ui: Ui_StatusWidget
    icon: QLabel
    title: QLabel
    message: QLabel
    
    parent: QWidget
    inDirection: int
    outDirection: int
    
    animation: QPropertyAnimation
    timer: QTimer

    def __init__(self, parent: QWidget, _in=EnterLeaveDuretion.TopIn, _out=EnterLeaveDuretion.RightOut):
        super(StatusWidget, self).__init__(parent)
        self.ui = Ui_StatusWidget()
        self.ui.setupUi(self)
        
        # 这些 icon title message 是一些不太重要的内容
        self.icon = self.ui.icon
        self.title = self.ui.title
        self.message = self.ui.message
        
        # 当那个 close 按钮被点击之后，调用停止动画(也就是离开动作，这应该是默认的行为，虽然很少用到)
        self.ui.close.clicked.connect(self.stop)

        # 留下这些初始化参数
        self.parent = parent
        self.inDirection = _in
        self.outDirection = _out
        
        # 动画的初始化与
        # 1. 设置使用动画的控件
        # 2. 设置目标控件的属性名称, 使用的父控件(第二个 self，可能会注册一些内部事件)
        # 3. 设置动画时间
        # 4. 设置动画效果
        self.animation = QPropertyAnimation(self, b"pos", self)
        self.animation.setDuration(1000)
        self.animation.setEasingCurve(QEasingCurve.Type.InOutQuart)
        
        # 一个简单的动画超时器
        # 如果被外部调用 start() 进入程序后，这个超时器就会在一定时间内触发离开操作
        self.timer = QTimer(self)
        self.timer.setInterval(1500)   # 超时器时间一定要比动画时间大
        self.timer.timeout.connect(self.stop)
        # self.timer.timeout.connect(self.timer.stop)
        
    def algorithmDirection(self, before: QPoint, after: QPoint, direction: int):
        """计算出入动画的起始与结束位置的核心函数

        Args:
            before (QPoint): 起始位置
            after (QPoint): 结束位置
            direction (int): 出入方位由 start() 或 stop() 中传入的内容
        """
        # 从右进出时会用到 parentWidth
        parentWidth = self.parent.width()
        # 从下进出时会用到 parentHeight
        parentHeight = self.parent.height()
        
        # 预留一点边缘空间
        spaceGap = 10
        
        # before and after
        beforeX, beforeY, afterX, afterY = 0,0,0,0
        
        """进入处理(上右下左)"""
        # 从上面进入，起始位置为x(不变), y(负到正)
        if direction == StatusWidget.EnterLeaveDuretion.TopIn:
            beforeX = afterX = parentWidth - self.width() - spaceGap
            beforeY = 0 - self.height() - spaceGap
            afterY = spaceGap
        # 从右边进入，如果要从上面出去，起始位置为x(大于父宽),y(为预留边缘空间)
        # 从右边进入，如果要从下面出去，起始位置为x(大于父宽),y(为父高减自身高与预留空间)
        elif direction == StatusWidget.EnterLeaveDuretion.RightIn:
            # 如果从顶部出去，将在距离顶部预留空间处
            if self.outDirection == StatusWidget.EnterLeaveDuretion.TopOut:
                beforeY = afterY = spaceGap
            # 如果从底部出去，将在距离底部预留空间处
            elif self.outDirection == StatusWidget.EnterLeaveDuretion.BottomOut:
                beforeY = afterY = parentHeight - self.height() - spaceGap
            beforeX = parentWidth + spaceGap
            afterX = parentWidth - self.width() - spaceGap
        # 从下面进入，如果要从上面出去，起始位置为x(大于父宽),y(为预留边缘空间)
        elif direction == StatusWidget.EnterLeaveDuretion.BottomIn:
            # 默认为右边出去
            beforeX = afterX = parentWidth - self.width() - spaceGap
            beforeY = parentHeight + spaceGap
            afterY = parentHeight - self.height() - spaceGap
        # 从左边进入，y(不变),x(从负到正)
        elif direction == StatusWidget.EnterLeaveDuretion.LeftIn:
            if self.outDirection == StatusWidget.EnterLeaveDuretion.TopOut:
                beforeY = afterY = spaceGap
            else:
                beforeY = afterY = parentHeight - self.height() - spaceGap
            beforeX = 0 - self.width() - spaceGap
            afterX = spaceGap
        
        """离开(上右下左)"""
        # 从上面离开，起始位置为x(不变)，y(正到负)
        if direction == StatusWidget.EnterLeaveDuretion.TopOut:
            beforeX = afterX = self.x()
            beforeY = self.y()
            afterY = 0 - self.height() - spaceGap
        # 从右边离开，起始位置为x(从小到大),y(不变)
        elif direction == StatusWidget.EnterLeaveDuretion.RightOut:
            beforeY = afterY = self.y()
            beforeX = self.x()
            afterX = parentWidth + spaceGap
        # 从下面离开，起始位置为x(不变),y(从小到大)
        elif direction == StatusWidget.EnterLeaveDuretion.BottomOut:
            beforeX = afterX = self.x()
            beforeY = self.y()
            afterY = parentHeight + spaceGap
        # 从左边离开，起始位置为x(正到负),y(不变)
        elif direction == StatusWidget.EnterLeaveDuretion.LeftOut:
            beforeY = afterY = self.y()
            beforeX = self.x()
            afterX = 0 - self.width() - spaceGap

        before.setX(beforeX)
        before.setY(beforeY)
        after.setX(afterX)
        after.setY(afterY)

        # print("beforeX: %d beforeY: %d" % (beforeX, beforeY))
        # print("afterX: %d afterY: %d" % (afterX, afterY))
        
        
    def start(self):
        before = QPoint()
        after = QPoint()
        
        self.algorithmDirection(before, after, self.inDirection)
        
        self.animation.setStartValue(before)
        self.animation.setEndValue(after)
        self.animation.start()
        
        # 超时器启动
        self.timer.start()

    def stop(self):
        before = QPoint()
        after = QPoint()

        self.algorithmDirection(before, after, self.outDirection)
        
        self.animation.setStartValue(before)
        self.animation.setEndValue(after)
        self.animation.start()
        
        # 超时器停止
        self.timer.stop()
    
    def setShowMessage(self, title: str, message: str):
        self.ui.title.setText(title)
        self.ui.message.setText(message)

    def setDirection(self, _in: EnterLeaveDuretion, _out: EnterLeaveDuretion):
        self.inDirection = _in
        self.outDirection = _out
        
    def setIcon(self, icon: QPixmap):
        iconSize = self.icon.size()
        self.icon.setPixmap(icon.scaled(iconSize))